package commons.ui.listener;

import org.eclipse.core.runtime.ListenerList;

/**
 * Provides dirty state management. Can be used as a stand alone dirty
 * management system (with internal dirty state): - add/removeDirtyListeners() -
 * setDirty() Can be hooked up to external dirty management systems (with
 * external dirty state): - fireDirtyEvent() Provides a fixed helper listener
 * for use by external dirty management systems. This fixed helper listener can
 * be conveniently located by this dirty manager.
 * 
 * @author Ihor
 */
public class DirtyManager {
    private boolean _isDirty = false;
    private final IDirtyListener _dirtyListener = new IDirtyListener() {
	public void dirtyStateChanged(DirtyEvent event) {
	    setDirty(event.dirtyState);
	}
    };
    private final ListenerList _dirtyListeners = new ListenerList(ListenerList.IDENTITY);
    private final Object _source;

    public DirtyManager(Object source) {
	_source = source;
    }

    /**
     * Helper object to connect this dirty manager to external dirty management
     * system
     * 
     * @return connector dirty listener
     */
    public IDirtyListener getDirtyListener() {
	return _dirtyListener;
    }

    /**
     * For direct state management of this dirty manager
     * 
     * @param value
     *            new dirty state
     * @return <code>true</code> whether this dirty manager changed state
     */
    public boolean setDirty(boolean value) {
	if (_isDirty ^ value) {
	    _isDirty = value;
	    fireDirtyEvent(value);
	    return true;
	}
	return false;
    }

    /**
     * Returns state of this dirty manager
     * 
     * @return
     */
    public boolean isDirty() {
	return _isDirty;
    }

    /**
     * Accepts new external listener for dirty state change events from this
     * dirty manager
     * 
     * @param listener
     */
    public void addDirtyListener(IDirtyListener listener) {
	_dirtyListeners.add(listener);
    }

    /**
     * Removes external dirty listener
     * 
     * @param listener
     */
    public void removeDirtyListener(IDirtyListener listener) {
	_dirtyListeners.remove(listener);
    }

    /**
     * External hook to allow external direct management systems use this
     * manager's listeners
     * 
     * @param value
     */
    public void fireDirtyEvent(boolean value) {
	if (_dirtyListeners.size() > 0) {
	    DirtyEvent dirtyEvent = new DirtyEvent(_source, value);
	    Object[] listeners = _dirtyListeners.getListeners();
	    for (Object element : listeners) {
		((IDirtyListener) element).dirtyStateChanged(dirtyEvent);
	    }
	}
    }
}
